import { computed, defineComponent, Ref, ref, watch } from 'vue';
import {
  getListBoxProps,
  getEditorEmits,
  useNamespace,
  useFocusAndBlur,
} from '@ibiz-template/vue3-util';
import { isNil } from 'ramda';
import './ibiz-list-box.scss';
import { ListBoxEditorController } from '../list-box-editor.controller';
import { ListBoxPickerEditorController } from '../list-box-picker-editor.controller';

export const IBizListBox = defineComponent({
  name: 'IBizListBox',
  props: getListBoxProps<
    ListBoxEditorController | ListBoxPickerEditorController
  >(),
  emits: getEditorEmits(),
  setup(props, { emit }) {
    const ns = useNamespace('list-box');

    const c = props.controller;

    const editorModel = c.model;

    let multiple: boolean = false;
    if (editorModel.editorParams) {
      if (editorModel.editorParams.multiple) {
        multiple = c.toBoolean(editorModel.editorParams.multiple);
      }
    }

    const codeList = (c as ListBoxEditorController).codeList;

    const editorType = editorModel.editorType;

    // 代码表数据（LISTBOX） or AC请求数据（LISTBOXPICKUP）
    const items = ref<readonly IData[]>([]);

    // 更新列表框选项
    const loadListBoxItems = async () => {
      if (Object.is('LISTBOX', editorType)) {
        const controller = c as ListBoxEditorController;
        controller.loadCodeList(props.data).then(_codeList => {
          items.value = _codeList;
        });
      } else if (Object.is('LISTBOXPICKUP', editorType)) {
        const controller = c as ListBoxPickerEditorController;
        if (controller.model.appDataEntityId) {
          const res = await controller.getServiceData(props.data);
          if (res) {
            items.value = res.data.map(item => ({
              value: item[controller.keyName],
              text: item[controller.textName],
            }));
          }
        }
      }
    };

    loadListBoxItems();

    // 当前模式
    const currentMode = computed(() => {
      if (codeList && codeList.orMode) {
        return codeList.orMode.toLowerCase();
      }
      return 'str';
    });

    // 值分隔符
    let valueSeparator = ',';
    if (codeList && codeList.valueSeparator) {
      valueSeparator = codeList.valueSeparator;
    }

    // 选中数组
    const selectArray: Ref<(string | number)[]> = ref([]);

    // 监听当前值生成selectArray
    watch(
      () => props.value,
      newVal => {
        if (!isNil(newVal)) {
          if (multiple) {
            let selectsArray: Array<string | number> = [];
            if (editorType === 'LISTBOX') {
              if (Object.is(currentMode.value, 'num') && items) {
                const num: number =
                  typeof newVal === 'string' ? parseInt(newVal, 10) : newVal;
                items.value.forEach((item: IData) => {
                  // eslint-disable-next-line no-bitwise
                  if ((num & item.value) === item.value) {
                    selectsArray.push(item.value);
                  }
                });
              } else if (Object.is(currentMode.value, 'str')) {
                if (newVal !== '') {
                  if (codeList && typeof newVal === 'string') {
                    selectsArray = newVal.split(valueSeparator);
                    if (codeList.codeItemValueNumber) {
                      for (let i = 0, len = selectsArray.length; i < len; i++) {
                        selectsArray[i] = Number(selectsArray[i]);
                      }
                    }
                  }
                }
              }
            } else if (editorType === 'LISTBOXPICKUP') {
              if (newVal !== '') {
                selectsArray = (newVal as string).split(valueSeparator);
              }
            }
            selectArray.value = selectsArray;
          } else {
            selectArray.value = [newVal];
          }
        } else {
          selectArray.value = [];
        }
      },
      { immediate: true, deep: true },
    );

    // 选中数据改变
    const onSelectArrayChange = (value: Array<string | number>) => {
      let _value;
      // 单多选
      if (multiple) {
        const values = [...value];
        if (Object.is('LISTBOX', editorType)) {
          // 根据代码表模式对值进行计算
          if (Object.is(currentMode, 'num')) {
            let temp: number = 0;
            values.forEach(item => {
              // eslint-disable-next-line no-bitwise
              temp |= parseInt(item as string, 10);
            });
            _value = temp;
          } else if (Object.is(currentMode, 'str')) {
            _value = values.join(valueSeparator);
          }
        } else if (Object.is('LISTBOXPICKUP', editorType)) {
          _value = values.join(valueSeparator);
        }
      } else {
        _value = value;
      }
      emit('change', _value);
    };

    // 聚焦失焦事件
    const { componentRef: editorRef } = useFocusAndBlur(
      () => emit('focus'),
      () => emit('blur'),
    );

    return {
      ns,
      items,
      selectArray,
      onSelectArrayChange,
      multiple,
      editorRef,
    };
  },
  render() {
    return (
      <div class={[this.ns.b()]} ref='editorRef'>
        {this.multiple ? (
          <el-checkbox-group
            class={this.ns.b('checkbox')}
            modelValue={this.selectArray}
            onChange={this.onSelectArrayChange}
          >
            {this.items.map((item, index: number) => (
              <el-checkbox
                key={index}
                label={item.value}
                disabled={this.disabled || this.readonly}
              >
                <span class={this.ns.e('text')}>{item.text}</span>
              </el-checkbox>
            ))}
          </el-checkbox-group>
        ) : (
          <el-radio-group
            class={this.ns.b('radio')}
            modelValue={this.selectArray[0]}
          >
            {this.items.map((item, index: number) => (
              <el-radio
                key={index}
                label={item.value}
                disabled={this.disabled || this.readonly}
                onChange={() => {
                  this.onSelectArrayChange(item.value);
                }}
              >
                <span class={this.ns.e('text')}>{item.text}</span>
              </el-radio>
            ))}
          </el-radio-group>
        )}
      </div>
    );
  },
});
